.TITLE DYDRV .IDENT /04.10/ ; ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; M. BAGGETT/R. PERRON 05-JUN-79 ; PREVIOUSLY MODIFIED BY: ; ; R. T. PERRON ; P. J. CARR ; P. J. BEZEREDI ; J. GALLANT ; T. LEKAS ; L. KOGAN ; G. MARIGOWDA ; ; MODIFIED FOR RSX-11M-PLUS V4.4 BY: ; ; D. CARROLL 20-JUL-1992 04.10 ; DC135 - CORRECT PROBLEMS IN INSURING THAT DYCOM ; IS CORRECTLY LOADED PRIOR TO SUCESSFUL ; ONLINE ; ; RX211- NPR FLOPPY DISK DRIVER ; ; FUNCTIONS RECOGNIZED: ; IO.RPB - READ PHYSICAL BLOCK (MAY READ ANY SECTOR ON DISK) ; IO.WPB - WRITE PHYSICAL BLOCK (MAY WRITE ANY SECTOR ON DISK) ; IO.WDD - WRITE DELETED DATA - WRITE ANY SECTOR ON DISK ; SETTING THE DELETED DATA MARK IN SECTOR HEADER ; ; THE FOLLOWING FUNCTION CODES OPERATE ON 256. WORD BLOCKS OF DATA ; (4 SECTORS FOR SINGLE DENSITY OR 2 SECTORS FOR DOUBLE DENSITY). ; THE DRIVER AUTOMATICALLY INTERLEAVES AND SKEWS SECTORS TO OPTIMIZE ; THE TRANSFER OF DATA SO THAT A LONG TRANSFER MAY BE DONE WITHOUT ; LOOSING A REVOLUTION OF THE DISK. THE INTERLEAVE FACTOR IS 2 AND ; THE SKEW FACTOR IS 6. ; IO.RLB - READ LOGICAL BLOCKS OF 256. WORDS ; IO.WLB - WRITE LOGICAL BLOCKS OF 256. WORDS. ; ; THE FOLLOWING FUNCTION CODES ARE USED TO INITIALIZE THE FLOPPY ; TO SINGLE OR DOUBLE DENSITY AND TO REPORT WHICH DENSITY THE CURRENT ; FLOPPY IS. ; IO.SMD - SET MEDIA DENSITY ; IO.SEC - SENSE MEDIA CHARACTERISTICS ; ; IF DELETED DATA IS READ, THE STATUS CODE RETURNED WILL BE IS.RDD, ; OTHERWISE IT WILL BE IS.SUC. ; .MCALL HWDDF$,PKTDF$,PCBDF$,QIOSY$,SCBDF$ QIOSY$ SCBDF$ ,,SYSDEF HWDDF$ ; DEFINE HARDWARE REGISTERS PKTDF$ ; DEFINE I/O PACKET OFFSETS PCBDF$ ; DEFINE PCB OFFSETS ; ; EQUATED SYMBOLS ; RETRY = 10 ; ERROR RETRY COUNT CEW = 4 ; RETRY COUNT FOR IO.SMD AND IO.SEC'S DYNUM = 6 ; NUMBER OF REGISTERS TO ERROR LOG MEMSIZ = 7600 ; 124K OF MEMORY IN 32 WORD BLOCKS APR5DS = 120000 ; APR5 DISPLACEMENT APR6DS = 140000 ; APR6 DISPLACEMENT LOOP = 1000 ; COUNTER TO CHECK FOR TR BIT ; ; U.CW2 BITS USAGE ; DELDAT = 100 ; DELETED DATA READ ERR1 = 2000 ; TIMEOUT ERROR BIT DEN = 4000 ; DENSITY BIT RSAE = 10000 ; READ STATUS AFTER ERROR SCHAR = 40000 ; SENSE MEDIA CHARACTERISTICS SILO = 100000 ; FUNCTION ISSUED WAS A SILO FUNCTION ; ; U.CW3 WORD USAGE ; SINGLE = 494. ; SINGLE DENSITY DOUBLE = 988. ; DOUBLE DENSITY ; ; DEVICE REGISTER OFFSETS AND BIT DEFINITIONS ; RXCS= 0 ; CONTROL STATUS REGISTER GO = 1 ; GO BIT UNIT = 20 ; UNIT SELECT BIT DONE = 40 ; DONE BIT INTEBL = 100 ; INTERRUPT ENABLE TR = 200 ; TRANSFER READY BIT (CPU-SILO) SDEN = 400 ; DENSITY BIT RX211 = 4000 ; RX211 INDICATOR BIT INIT = 40000 ; INITIALIZATION BIT ERR = 100000 ; ERROR BIT RXDB = 2 ; DATA BUFFER REGISTER RXES = 2 ; RX211 ERROR STATUS REGISTER CRCERR = 1 ; CRC ERROR BIT INITDN = 4 ; INITIALIZE DONE BIT RXACLO = 10 ; RX221 AC LOW BIT DENERR = 20 ; DENSITY ERROR BIT DRVDEN = 40 ; SELECTED DRIVE'S DENSITY BIT DELDAT = 100 ; DELETED DATA BIT (USED IN U.CW2 ALSO) DRVRDY = 200 ; SELECTED DRIVE READY BIT UNTSEL = 400 ; UNIT SELECTED BIT WCOVFL = 2000 ; WORD COUNT OVERFLOW BIT NXM = 4000 ; NON-EXISTENT MEMORY BIT ; ; FUNCTION CODES ; FILL = INTEBL!0!GO ; FILL SILO EMPTY = INTEBL!2!GO ; EMPTY SILO WRITE = INTEBL!4!GO ; WRITE A SECTOR READ = INTEBL!6!GO ; READ A SECTOR SETDEN = INTEBL!10!GO ; SET MEDIA DENSITY MRDS = INTEBL!12!GO ; MAINTENANCE READ STATUS WRTDD = INTEBL!14!GO ; WRITE DELETED DATA RDERC = INTEBL!16!GO ; READ ERROR CODE ; ; LOCAL DATA ; ; RETRY COUNT TABLE (INDEXED BY CONTROLLER NUMBER) ; DYPCB: .WORD 0 ; ADD OF PCB OF DYCOM DYCOM: .RAD50 /DYCOM/ ; NAME OF DY DATA COMMON BFLAG: .BLKW R$$X21 ; BUFFERING DATA FLAG ; = 0 DO NOT BUFFER DATA ; = 1 BUFFER DATA RTTBL: .BLKW R$$X21 ; ERROR RETRY COUNT FOR CURRENT UNIT CSRSV: .BLKW R$$X21 ; WORD TO SAVE CSR FUNCTION CODE COUNT: .BLKW R$$X21 ; COUNT OF BYTES TRANSFERED IN IB WCOUNT: .BLKW R$$X21 ; COUNT OF DATA LEFT TO BE MOVED (FOR ; WRITE OPERATION ONLY) BUFLEN: .BLKW R$$X21 ; LENGTH OF INTERMEDIATE BUFFER (IB) PHYADD: .BLKW R$$X21 ; PHYSICAL ADD OF USER BUFFER (LO) HIADD:: .BLKW R$$X21 ; PHYSICAL ADD OF USER BUFFER (HI) LOPHYA: .BLKW R$$X21 ; LO ORDER 16 BITS OF PHY ADD (IB) HIPHYA: .BLKW R$$X21 ; HI ORDER 2 BITS OF PHY ADD (IB) DYPTR: .BLKW R$$X21 ; POINTER IN DY DATA COMMON TEMP: .BLKW R$$X21 ; TEMPORY COUNTER WHEN DOING MULTIPLE ; FORKS RETPTR: .BLKW R$$X21 ; TEMPORY STORAGE FOR RET ADDRESS OF ; SUBROUTINE WHEN CALLING $FORK ; NOTHING CAN BE ON STACK WHEN ; CALLING $FORK CONCNT: .WORD 0 ;# OF CONTROLLERS CONNECTED TO DYCOM ; ; MAKE GTPKT$ A LOCAL MACRO ; .MACRO GTPKT$ DEV,NCTRLR,ADDR,UCBSV,SUC CALL @GTPKT .IF B BCC 65535$ RETURN 65535$: .IFF BCS ADDR .ENDC .IF B $$$=0 .IF B .IF EQ $$$ MOV R5,S.OWN(R4) .ENDC .ENDC .IFF .IF GT NCTRLR-1 MOV R5,UCBSV(R3) .IFF MOV R5,UCBSV .ENDC .ENDC .ENDM ; ; EXECUTIVE ENTRY POINT VECTOR TABLE ; EXEVEC: .WORD 0 ; FLAG FOR VECTOR NOT YET FILLED ALOCB: .WORD $ALOCB BLXI: .WORD $BLXIO DEACB: .WORD $DEACB DTOER: .WORD $DTOER DVERR: .WORD $DVERR ERRSQ: .WORD $ERRSQ FNDSP: .WORD $FNDSP FORK: .WORD $FORK FRKHD: .WORD $FRKHD GTPKT: .WORD $GTPKT HFMSK: .WORD $HFMSK IODON: .WORD $IODON LDREG: .WORD $LDREG MPPHY: .WORD $MPPHY MPUBM: .WORD $MPUBM SCERR: .WORD $SCERR SRNAM: .WORD $SRNAM STMAP: .WORD $STMAP VOLVD: .WORD $VOLVD ; EXEVCL=<<<.-EXEVEC>/2>-1> ; ; ; DRIVER DISPATCH TABLE ; DDT$ DY,R$$X21,,,,NEW ; GENERATE DISPATCH TABLE ;+ ; *** - DYINI FLOPPY DISK CONTROLLER INITIATOR ; ; THIS ROUTINE IS ENTERED FROM THE QIO DIRECTIVE WHEN AN I/O REQUEST ; IS QUEUED AND AT THE END OF A PREVIOUS I/O OPERATION TO PROPOGATE THE ; EXECUTION OF THE DRIVER. IF THE SPECIFIED CONTROLLER IS NOT BUSY, ; THEN AN ATTEMPT IS MADE TO DEQUEUE THE NEXT I/O REQUEST. OTHERWISE ; A RETURN TO THE CALLER IS EXECUTED. IF THE DEQUEUE ATTEMPT IS SUCCESSFUL ; THE NEXT I/O OPERATION IS INITIATED. A RETURN TO THE CALLER IS THEN ; EXECUTED. ; ; INPUTS: ; R5 - ADDRESS OF UCB OF CONTROLLER TO BE INITIATED ; ; OUTPUTS: ; IF THE CONTROLLER ASSOCIATED WITH THE SPECIFIED UCB IS NOT ; BUSY AND AN I/O REQUEST IS WAITING TO BE PROCESSED, THE REQUEST ; IS DEQUEUED AND THE DRIVER INITIATES THE REQUESTED FUNCTION. ; ;- .ENABL LSB DYINI: GTPKT$ DY,R$$X21 ; GET NEXT I/O PACKET ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT ; ; R1 - ADDRESS OF THE I/O PACKET ; R2 - PHYSICAL UNIT NUMBER OF DEVICE TO BE INITIATED ; R3 - CONTROLLER INDEX ; R4 - ADDRESS OF SCB ; R5 - ADDRESS OF THE UCB ; ; FLOPPY DISK I/O REQUEST PACKET FORMAT ; ; WD. 00 -- I/O QUEUE THREAD WORD ; WD. 01 -- REQUEST PRIORITY, EVENT FLAG NUMBER ; WD. 02 -- ADDRESS OF TCB OF THE REQUESTING TASK ; WD. 03 -- POINTER TO SECOND LUN WORD OF REQUESTING TASKS HEADER ; WD. 04 -- CONTENTS OF FIRST LUN WORD ( UCB ADDRESS) ; WD. 05 -- I/O FUNCTION CODE (IO.RLB, IO.RPB, IO.WLB, IO.WPB, ; IO.WDD, IO.SMD OR IO.SEC) ; WD. 06 -- VIRTUAL ADDRESS OF I/O STATUS BLOCK ; WD. 07 -- RELOCATION BIAS OF I/O STATUS BLOCK ; WD. 10 -- I/O STATUS BLOCK ADDRESS DISPLACEMENT + 140000 ; WD. 11 -- VIRTUAL ADDRESS OF AST SERVICE ROUTINE ; WD. 12 -- RELOCATION BIAS OF DATA BUFFER ; WD. 13 -- BUFFER ADDRESS OF I/O TRANSFER ; WD. 14 -- NUMBER OF BYTES TO TRANSFER ; WD. 15 -- NOT USED (IGNORED) ; WD. 16 -- LOW BYTE MUST BE ZERO, HIGH BYTE NOT USED ; WD. 17 -- LOGICAL OR PHYSICAL BLOCK NUMBER ; WD. 20 -- NOT USED ; ; DRIVER USAGE OF WORDS IN I/O PACKET ; I.PRM+6 (WD. 15) - STATUS REGISTER AFTER INTERRUPT ; I.PRM+10 (WD. 16) - LOGICAL OR PHYSICAL BLOCK NUMBER ; I.PRM+12 (WD. 17) - SIZE OF "THIS" TRANSFER ; I.PRM+14 (WD. 20) - PHYSICAL SECTOR NUMBER (1-26.) ; I.PRM+15 (WD. 20) - PHYSICAL TRACK NUMBER (0-76.) ; ; ; WHEN BRINGING RX02 CONTROLLER ONLINE, HRC ISSUES AN IO.SMD TO ; DYDRV. OFFSETS I.PRM+12 AND I.PRM+14 GET RELOCATED TO I.PRM+14 ; AND I.PRM+16 BY $VOLVD ROUTINE. $VOLVD THINKS THAT IT IS AN ; IO.STC FUNCTION AND DOES THE RELOCATE. IN $IOFIN, IF I.PRM+16 ; IS NOT A VALID BUFFER ADDESS (> 140000) OR ZERO, THE SYSTEM CAN ; CRASH OR DESTROY A LOCATION IN MEMORY.SINCE IO.SMD IS ONLY USED ; FOR RX02 DEVICE, A SPECIAL CHECK IS MADE IN THE DRIVER FOR IO.STC. ; IF THE FUNCTION IS IO.STC THEN I.PRM+16 IS CLEARED. ; THE DRIVER DOES NOT USE LOCATION I.PRM+16. ; ; ; ; INITIALIZE DRIVER ; MOV #RETRY,RTTBL(R3); SET RETRY COUNT BIC #^C,U.CW2(R5); CLEAR DYNAMIC UCB FLAG BITS CALL @VOLVD ;VALIDATE VOLUME VALID BCS 20$ ; IF CS WE FAILED MOV I.FCN(R1),-(SP) ; GET FUNCTION CODE BIC #7,(SP) ; REMOVE QUALIFIER BITS CMP #IO.STC,(SP) ; IS IT A SET CHARACTERISTICS FUNCTION ? BNE 5$ ; NO CLR I.PRM+16(R1) ; CLEAR THIS FOR THE BLOCK LOCK CODE ; IN $IOFIN 5$: TST (SP)+ ; RESTORE STACK LEVEL TST R0 ; TRANSFER FUNCTION? BPL 20$ ; IF PL NO TSTB I.PRM+10(R1) ; HIGH BLOCK SPECIFIED? BEQ 30$ ; IF EQ NO 10$: JMP 380$ ; YES, ERROR 20$: JMP 440$ ; ERROR ; ; CHECK FOR A VALID FUNCTION ; 30$: MOV S.CSR(R4),R2 ; RETRIEVE CSR ADDRESS CMPB #IO.SEC/256.,I.FCN+1(R1) ; VALID FUNCTION? BNE 60$ ; IF NE, IT MUST BE READ OR WRITE MOVB #CEW,RTTBL(R3) ; IO.SEC AND IO.SMD ONLY 4 RETRIES MOV I.FCN(R1),R0 ; GET FUNCTION CODE BIC #7,R0 ; REMOVE QUALIFIER BITS CMP #IO.SEC,R0 ; SENSE CHARACTERISTICS? BNE 40$ ; IF NE NO JMP DYSEC ; GET DISKETTE CHARACTERISTICS 40$: CMP #IO.SMD,R0 ; SET MEDIA DENSITY? BNE 50$ ; IF NE NO BITB #US.MNT!US.FOR,U.STS(R5) ; DEVICE MOUNTED? BEQ 50$ ; IF EQ YES MOV R0,I.FCN(R1) ; SET FUNCTION CODE WITHOUT MODIFIERS JMP DYSMD ; SET DISKETTE DENSITY 50$: MOV #IE.IFC&377,R0 ; RETURN ERROR CODE JMP 420$ ; EXIT 60$: ; REF LABEL ; ; SET UP MAPPING AND FIRST DISK ADDRESS ; BIT #HF.UBM,@HFMSK ; UNIBUS MAP PRESENT ? BEQ 61$ ; NO CLR BFLAG(R3) ; NO BUFFERING NEEDED CALL @STMAP ; SET UP 11/70 UNIBUS MAPPING ADDRS SWAB U.BUF(R5) ; POSITION EXTENDED MEMORY BITS BR 69$ 61$: MOV R2,-(SP) ; SAVE R2 MOV U.BUF(R5),R0 ; GET ADDRESS EXTENSION BITS MOVB U.BUF+1(R5),-(SP); SAVE THE EXTENSION BITS MOV U.BUF+2(R5),R2 ; GET USER BUFFER ADDRESS ADD I.PRM+4(R1),R2 ; FIND END OF BUFFER ADCB (SP) ; GET ANY LEFT OVER CARRY BITB #^C303,(SP)+ ; 22 BIT ADDRESS ? BNE 62$ ; YES - DO BUFFERING ASH #4,R0 ; GET BITS 17 & 18 INTO POSITION BR 63$ ; 62$: MOV #1,BFLAG(R3) ; DO BUFFERING MOV (SP)+,R2 ; RESTORE R2 BR 65$ ; 63$: CLR BFLAG(R3) ; NO BUFFERING NEEDED BIC #^C<30000>,R0 ; ISOLATE BITS 12 & 13 MOV R0,U.BUF(R5) ; SAVE HI BITS OF ADDRESS MOV (SP)+,R2 ; RESTORE R2 BR 69$ ; 65$: MOV I.PRM+2(R1),PHYADD(R3); PHYSICAL ADD OF USER BUFFER(LO) CLR HIADD(R3) ; CLEAR HIGH ADDRESS MOVB I.PRM+1(R1),HIADD(R3); PHYSICAL ADD OF USER BUFFER (HI) MOV R1,-(SP) ; SAVE R1 MOV R2,-(SP) ; SAVE R2 MOV DYPCB,R0 ; GET PCB ADD OF DYCOM MOV P.REL(R0),R1 ; RELOCATION BIAS MOV R1,DYPTR(R3) ; INITIALIZE POINTER INTO DYCOM TST R3 ; IS THIS THE FIRST CONTROLLER ? BEQ 67$ ; YES MOV P.SIZE(R0),R2 ; GET SIZE OF DYCOM ASR R2 ; DIVIDE IN HALF ADD R2,R1 ; POINT TO SECOND HALF OF IB ADD R2,DYPTR(R3) ; POINT INTO SECOND HALF OF COMMON 67$: MOV #APR6DS,R2 ; APR6 DISPLACEMENT CALL @MPPHY ; GET 18BIT PYS ADD OF IB ASH #4,R1 ; PUT BITS 17 & 18 OF ADD ; INTO BITS 12 & 13 BIC #^C<30000>,R1 ; ISOLATE BITS 12 AND 13 MOV R1,HIPHYA(R3) ; SAVE HI BITS OF ADD OF IB MOV R1,U.BUF(R5) ; SET UP EXTENDED BITS MOV R2,LOPHYA(R3) ; SAVE LO BITS OF ADD OF IB MOV R2,U.BUF+2(R5) ; SET UP LO BITS OF ADD FOR ; DATA TRANSFER MOV P.SIZE(R0),R1 ; COMPUTE LENGTH OF IB ASH #6,R1 ; GET LENGTH IN BYTES TST R3 ; IS THIS THE FIRST CONTROLLER ? BEQ 68$ ; YES ASH #-1,R1 ; DIVIDE BY 2 - TWO CONTROLLERS SHARING ; ONE BUFFER 68$: MOV R1,BUFLEN(R3) ; SAVE LENGTH OF IB MOV R1,COUNT(R3) ; MOV U.CNT(R5),WCOUNT(R3); COUNT OF DATA TO BE MOVED FOR A ; WRITE FUNCTION MOV (SP)+,R2 ; RESTORE REG MOV (SP)+,R1 ; CMPB #IO.WLB/256.,I.FCN+1(R1); WRITE FUNCTION ? BNE 69$ ; NO CLR COUNT(R3) ; NO BYTES TRANSFERED YET ; INITIATE CALL TO BLXIO 69$: MOV I.PRM+12(R1),R0 ; GET PHYSICAL OR LOGICAL BLOCK NUMBER BITB #IO.RPB&377,I.FCN(R1) ; IS IT READ/WRITE PHYSICAL? BNE 70$ ; IF NE YES ASL R0 ; CONVERT TO LOGICAL SECTOR NO. (LBN*2) BIT #DEN,U.CW2(R5) ; DOUBLE DENSITY? BNE 70$ ; IF NE YES ASL R0 ; SINGLE DEN - LBN*4 70$: MOV R0,I.PRM+10(R1) ; STORE IT 80$: MOV S.PKT(R4),R3 ; GET I/O PACKET ADDRESS CALL TRKSEC ; CONVERT BLOCK # TO TRACK/SECTOR BCC 82$ ; IF CC -> OK JMP 10$ ; CS -> BAD BLOCK NUMBER 82$: MOV S.CSR(R4),R2 ; GET ADDRESS OF CSR CMPB #IO.WLB/256.,I.FCN+1(R3) ; WRITE FUNCTION? BEQ 822$ ; IF EQ YES JMP 190$ ; MUST BE READ FUNCTION ; ; FILL SILO BEFORE WRITE ; 822$: MOVB S.CON(R4),R1 ; GET CONTROLLER INDEX TST BFLAG(R1) ; BUFFER DATA ? BEQ 88$ ; NO TST COUNT(R1) ; IS THE IB FULL WITH DATA ? BGT 88$ ; YES CMP BUFLEN(R1),WCOUNT(R1); IS THE I/O TRANSFER ; GREATER THAN THE IB BGT 83$ ; BGT - NO SUB BUFLEN(R1),WCOUNT(R1); UPDATE BYTES LEFT TO COMPLETE TRAN MOV BUFLEN(R1),TEMP(R1); NUMBER OF BYTES TO BE MOVED BR 84$ ; 83$: MOV WCOUNT(R1),TEMP(R1); NUMBER OF BYTES TO BE MOVED CLR WCOUNT(R1) ; AFTER THIS MOVE, I/O TRANS IS COMPLETE 84$: MOV TEMP(R1),COUNT(R1); LENGTH OF DATA IN IB 86$: CALL BLXIO ; FILL IB WITH MORE DATA ADD #<256./100>,DYPTR(R1) ; BUMP POINTER INTO DYCOM (32 WORD BLOCKS) SUB #256.,TEMP(R1) ; DECREMENT TEMPORY COUNT BLE 87$ ; IB IS FULL TST $FRKHD ; ANYONE WAITING TO FORK ? BEQ 86$ ; IF EQ NO -> DO SOME MORE CALL @FORK ; LET SOMEONE ELSE DO SOME WORK MOVB S.CON(R4),R1 ; GET CONTROLLER INDEX MOV S.CSR(R4),R2 ; GET CSR ADDRESS MOV S.PKT(R4),R3 ; GET I/O PACKET ADDRESS BR 86$ ; DO SOME MORE BLXIO 87$: BIC #30000,U.BUF(R5); RESET EXTENDED ADDRESSING BITS BIS HIPHYA(R1),U.BUF(R5); TO POINT TO BEG OF IB MOV LOPHYA(R1),U.BUF+2(R5); RESET LO BITS OF IB MOV R2,-(SP) ; SAVE REG MOV DYPCB,R2 ; GET PCB OF DYCOM MOV P.REL(R2),DYPTR(R1); INITIALIZE POINTER INTO DYCOM TST R1 ; ONE CONTROLLER BEQ 877$ ; YES MOV P.SIZE(R2),-(SP); GET SIZE OF REGION ASR (SP) ; CUT IN HALF ADD (SP)+,DYPTR(R1) ; POINT INTO SECOND HALF OF REGION 877$: MOV (SP)+,R2 ; RESTORE REG 88$: MOVB #FILL,U.BUF(R5) ; SET FILL SILO FUNCTION 90$: BIT #DEN,U.CW2(R5) ; DOUBLE DENSITY? BEQ 100$ ; IF EQ NO BIS #SDEN,U.BUF(R5) ; YES-SET DOUBLE DENSITY BIT 100$: BIS #SILO,U.CW2(R5) ; INDICATE SILO FUNCTION MOVB S.CON(R4),R1 ; RETRIEVE CONTROLLER INDEX MOV U.BUF(R5),CSRSV(R1) ; SAVE FUNCTION CODE MOV U.BUF(R5),(R2) ; INITIATE FUNCTION BIT #HF.UBM,@HFMSK ; UNIBUS MAP PRESENT ? BEQ 105$ ; N0 MOV R2,-(SP) ; SAVE REGISTER CALL @MPUBM ; MAP 11/70 UNIBUS TO TRANSFER MOV (SP)+,R2 ; RESTORE REGISTER 105$: MOV U.BUF+2(R5),R0 ; GET BUFFER ADDRESS MOV #128.,R1 ; DEFAULT TO A 128. BYTE TRANSFER BIT #DEN,U.CW2(R5) ; DOUBLE DENSITY DISKETTE? BEQ 110$ ; IF EQ NO ASL R1 ; CHANGE DEFAULT TO 256. BYTES 110$: CMP U.CNT(R5),R1 ; FULL TRANSFER LEFT? BHIS 120$ ; IF HIS YES MOV U.CNT(R5),R1 ; NO, GET RESIDUAL COUNT 120$: MOV R1,I.PRM+12(R3) ; STORE BYTES BEING TRANSFERRED 130$: BITB #TR!DONE,(R2) ; TRANSFERRED? BMI 140$ ; IF MI YES BEQ 130$ ; IF EQ NO BR 160$ ; ERROR 140$: ASR R1 ; WORD COUNT MOV R1,RXDB(R2) ; LOAD WORD COUNT 150$: BITB #TR!DONE,(R2) ; TRANSFERRED? BMI 270$ ; IF MI YES - R0 HAS BUFFER ADDRESS BEQ 150$ ; IF EQ NO 160$: MOV RXES(R2),I.PRM+6(R3) ; SAVE STATUS JMP DYRTY ; ERROR, RETRY OPERATION ; ; EMPTY SILO AFTER READ ; 170$: MOVB #EMPTY,U.BUF(R5) ; SET EMPTY SILO FUNCTION BR 90$ ; SAME AS FILL SILO PROCEDURE ; ; INITIATE TRANSFER BETWEEN SILO AND DISK ; 180$: MOV S.PKT(R4),R3 ; GET I/O PACKET ADDRESS MOV S.CSR(R4),R2 ; GET CSR ADDR MOVB #WRITE,U.BUF(R5);ASSUME WRITE FUNCTION MOV I.FCN(R3),R1 ; GET FUNCTION CODE BIC #7,R1 ; REMOVE QUALIFIER BITS CMP #IO.WDD,R1 ; WRITE WITH DELETED DATA? BNE 200$ ; IF NE NO MOVB #WRTDD,U.BUF(R5) ; SET "WRITE DELETED DATA" FUNCTION BR 200$ ; 190$: MOVB #READ,U.BUF(R5) ; SET READ FUNCTION 200$: BIT #DEN,U.CW2(R5) ; DOUBLE DENSITY? BEQ 210$ ; IF EQ NO BIS #SDEN,U.BUF(R5) ; YES-SET DENSITY BIT 210$: TSTB U.UNIT(R5) ; UNIT 1? BEQ 220$ ; IF EQ NO BIS #UNIT,U.BUF(R5) ; YES, SET TO SELECT UNIT 1 220$: MOVB S.CON(R4),R1 ; RETRIEVE CONTROLLER INDEX MOV U.BUF(R5),CSRSV(R1) ; SAVE FUNCTION CODE MOV #LOOP,R0 ; SET UP COUNTER MOV U.BUF(R5),(R2) ; INITIATE FUNCTION 230$: BITB #TR!DONE,(R2) ; TRANSFERRED? BMI 240$ ; IF MI YES BEQ 235$ ; TR NOT SET - DECREMENT COUNTER BR 160$ ; ERROR 235$: DEC R0 ; DECREMENT COUNTER BNE 230$ ; KEEP ON CHECKING BIT MOVB S.CON(R4),R3 ; GET CONTROLLER INDEX MOV S.PKT(R4),R1 ; GET I/O PACKET ADDRESS MOV #1,RTTBL(R3) ; JUST DO ONE RETRY JMP 620$ ; INITIALIZE DRIVE TO RECOVER FROM ; POWER OFF PROBLEM 240$: MOVB I.PRM+14(R3),RXDB(R2) ; LOAD SECTOR NUMBER 250$: BITB #TR!DONE,(R2) ; TRANSFER READY OR DONE? BMI 260$ ; IF MI TRANSFER READY BEQ 250$ ; IF EQ LOOP BR 160$ ; ERROR, NO TRANSFER REQUEST 260$: MOVB I.PRM+15(R3),R0 ; LOAD TRACK NUMBER IN R0 270$: MOVB S.ITM(R4),S.CTM(R4) ; SET TIMEOUT COUNT 280$: BIS #S2.ACT,S.ST2(R4) ; SHOW I/O IS ACTIVE MOV R0,RXDB(R2) ; LOAD TRACK, BUFFER ADDRESS, OR ASCII I ; ; DYPWF - POWER FAIL ENTRY POINT ; POWER FAIL IS HANDLED BY THE DEVICE TIMING OUT, THEREFORE ; NO WORK IS DONE HERE. IT WILL BE HANDLED WHEN THE DEVICE ; TIME OUT ENTRY IS EXECUTED. ; ; ; DYCAN - CANCEL I/O ENTRY POINT ; CANCEL I/O IS A NOP OP FOR FILE STRUCTURED DEVICES ; DYPWF: ;;; DYCAN: RETURN ;;; ;+ ; ** -- DYKRB -- DY CONTROLLER STATUS CHANGE ROUTINE ; ; THIS ROUTINE WILL HANDLE SETTING CONTROLLER ONLINE/OFFLINE ; ; THIS ROUTINE HAS BEEN ADDED FOR 22 BIT QBUS PROCESSORS. THE ; FOLLOWING REQUIREMENTS MUST BE MET TO HAVE THIS CONTROLLER ; BROUGHT ONLINE: ; ; 1.DYCOM REGION MUST EXIST. DYCOM IS THE INTERMEDIATE BUFFER (IB). ; 2.DYCOM MUST BE LOADED IN THE FIRST 124K OF PHYSICAL MEMORY ; ; THIS ROUTINE WILL ALSO INSURE THAT THE DYCOM REGION IS ; NOT CHECKPOINTABLE, NOT SHUFFLEABLE, AND FIXED IN MEMORY. ; ; INPUTS ; ; R2 = KRB ADDRESS ; R3 = CTB ADDRESS ; C = 0 REQUEST OFFLINE TO ONLINE TRANSITION ; C = 1 REQUEST ONLINE TO OFFLINE TRANSTION ; $SCERR = 1 PRESET TO SUCESS ; ; OUTPUTS ; ; $SCERR < 0 OPERATION IS FAILURE ; $CSERR CONTAINS FAILURE CODE ; $SCERR = 1 OPERATION IS SUCESS ; ;- DYKRB: BCC 279$ ; IF CC -> GO TO TRANSITION TO ONLINE BIT #HF.UBM,@HFMSK ; UNIBUS MAP PRESENT ? BNE 290$ ; YES DEC CONCNT ; DECREMENT # OF CONTROLLERS USING DYCOM BNE 290$ ; IF NE , THERE ARE STILL MORE MOV R0,-(SP) ; SAVE R0 MOV DYPCB,R0 ; GET ADDRESS OF DYCOM BEQ 278$ ; IF EQ -> DON'T CLEAR BIT - DYPCB NOT SET UP BIC #P2.LMA,P.ST2(R0);CLEAR THE 'LEAVE ME ALONE' BIT 278$: MOV (SP)+,R0 ; RESTORE R0 BR 290$ ; AND RETURN 279$: TST EXEVEC ; IF DONE ALREADY BNE 2$ ; SKIP THIS MOV R2,-(SP) ; SAVE R2 MOV R3,-(SP) ; SAVE R3 MOV KINAR6,-(SP) ; SAVE KINAR6 MOV @#112,R0 ; GET ADDRESS OF TABLE OF ENTRIES MOV (R0),R0 ; GET ADDRESS OF APR BIAS (1ST WORD IN TABLE) MOV (R0),KINAR6 ; MAP COMMON THROUGH I-SPACE APR6 MOV #EXEVEC,R3 ; POINT TO VECTOR MOV #EXEVCL,R2 ; SPECIFY LENGTH OF VECTOR CALL @#140004 ; TRANSLATE THE VECTOR MOV (SP)+,KINAR6 ; RESTORE KINAR6 MOV (SP)+,R3 ; RESTORE R3 MOV (SP)+,R2 ; RESTORE R2 2$: BIT #HF.UBM,@HFMSK ; UNIBUS MAP PRESET ? BNE 290$ ; YES - NOTHING TO DO MOV R0,-(SP) ; SAVE R0 MOV R1,-(SP) ; SAVE R1 MOV R2,-(SP) ; SAVE R2 MOV R3,-(SP) ; SAVE R3 MOV #DYCOM,R3 ; GET ADD OF DYCOM NAME CALL @SRNAM ; SEARCH FOR NAMED REGION BCS 282$ ; DOES NOT EXIST - CANNOT BRING ; CONTROLLER ONLINE MOV R2,DYPCB ; SAVE ADDRESS OF DYCOM'S PCB MOV R2,R1 ; DYCOM'S PCB ADDRESS ASSUME PS.OUT,100000 ; TST P.STAT(R1) ; IS REGION IN MEMORY ? BPL 281$ ; YES TSTB P.RMCT(R1) ; have we already called $LDREG BNE 27$ ; yup, don't mix and match MOV R4,-(SP) ; Save R4 MOV R5,-(SP) ; and R5 MOV R1,R4 ; copy the PCB address MOV P.MAIN(R4),R5 ; and the main PCB address CALL @FNDSP ; attempt to allocate region now ... MOV DYPCB,R1 ; reset the PCB address BCS 27$ ; if CS, space is not available BIC #PS.OUT,P.STAT(R1) ; flag partition as loaded BR 28$ ; and finish up ... 27$: ; reference label INCB P.RMCT(R1) ; BUMP RESIDENT MAPPED TASK COUNT MOVB #160.,P.PRI(R1) ; SET UP REGION PRIORITY ; MAKE THE PRIORITY HIGH SO IT GETS ; QUEUED UP QUICKLY CALL @LDREG ; BRING REGION INTO MEMORY 28$: MOV DYPCB,R1 ; RESTORE PCB ADDRESS MOV (SP)+,R5 ; restore R5 MOV (SP)+,R4 ; and R4 281$: MOV P.REL(R1),R3 ; GET STARTING PHYSICAL ADD OF DYCOM ADD P.SIZE(R1),R3 ; GET ENDING ADDRESS OF DYCOM CMP R3,#MEMSIZ ; IS DYCOM IN FIRST 124K MEMORY ? BHI 282$ ; NO - DO NOT BRING CONTROLLER ONLINE BIS #PS.CHK!PS.FXD!PS.NSF,P.STAT(R1); MAKE SURE DYCOM IS ; NOT CHK,NOT SHUFF,AND FIXED IN MEMORY ASSUME PS.OUT,100000 ; TST P.STAT(R1) ; IS THE PARTITION STILL OUT? BMI 282$ ; YES, DON'T COME ONLINE JUST YET ... BIS #P2.LMA!P2.RON,P.ST2(R1); DON'T TOUCH PARTITION INC CONCNT ; INCREMENT # OF CONTROLLERS USING DYCOM MOVB #1,P.RMCT(R1) ; Indicate one attacher BR 285$ ; OK TO BRING DEVICE ONLINE 282$: MOVB #IE.PNT,@SCERR ; ERROR - PARTITION NOT THERE 285$: MOV (SP)+,R3 ; RESTORE R3 MOV (SP)+,R2 ; RESTORE R2 MOV (SP)+,R1 ; RESTORE R1 MOV (SP)+,R0 ; RESTORE R0 290$: RETURN ; DONE - RETURN ;+ ; ** --DYUCB -- DY UNIT STATUS CHANGE ROUUTINE ; ; THIS ROUTINE WILL HANDLE SETTING EACH UNIT ONLINE/OFFLINE ; ; THIS ROUTINE WILL JUST RETURN ; DYUCB: RETURN ;+ ; *** - $DYINT - RX211 FLOPPY DISK INTERRUPT ENTRY POINT ; ;- INTSE$ DY,PR5,R$$X21 ;;; GENERATE INTERRUPT SAVE CODE MOV U.SCB(R5),R4 ; GET SCB ADDRESS TSTB S.STS(R4) ; IS THE DRIVE BUSY ? BNE 295$ ; IF NE YES RETURN ; IGNORE SPURIOUS INTERRUPTS 295$: MOV R3,-(SP) ; SAVE REGISTER MOV U.SCB(R5),R4 ;;; GET SCB ADDRESS MOV S.PKT(R4),R3 ;;; GET I/O PACKET ADDRESS MOV S.CSR(R4),R4 ;;; GET CSR ADDRESS MOV RXDB(R4),I.PRM+6(R3) ;;; SAVE CONTROLLER STATUS MOV (SP)+,R3 ;;; RESTORE REGISTER BIT #RXACLO,RXES(R4);POWER OFF ? BEQ 297$ ;NO RETURN ;POWER OFF - IGNORE INTERRUPT 297$: CLR (R4) ;;; DISABLE INTERRUPTS CALL @FORK ;;; CREATE A SYSTEM PROCESS MOV R4,R2 ; COPY CSR ADDRESS MOV U.SCB(R5),R4 ; GET SCB ADDRESS MOVB S.CON(R4),R3 ; GET CONTROLLER INDEX BIT #SCHAR,U.CW2(R5); SENSE CHARACTERISTICS ? BNE DYSEN ; IF NE YES TST (R2) ; ANY ERRORS? BPL 300$ ; IF PL NO ERRORS JMP DYRTY ; YES-RETRY FUNCTION 300$: ASRB RTTBL+1(R3) ; INITIALIZE IN PROGRESS? BCS 360$ ; IF CS YES MOV S.PKT(R4),R3 ; GET I/O PACKET ADDRESS CMP #IO.SMD,I.FCN(R3) ; SET MEDIA DENSITY? BNE 310$ ; IF NE NO JMP 410$ ; YES, FINISH I/O 310$: CMPB #IO.RLB/256.,I.FCN+1(R3) ; READ FUNCTION? BNE 340$ ; IF NE NO TST U.CW2(R5) ; SILO FUNCTION? BMI 330$ ; IF MI YES BITB #DELDAT,I.PRM+6(R3) ; DELETED DATA READ? BEQ 320$ ; IF EQ NO BISB #DELDAT,U.CW2(R5) ; YES 320$: JMP 170$ ; GO EMPTY SILO 330$: BIC #SILO,U.CW2(R5) ; CLEAR SILO FLAG CALL NXTSEC ; UPDATE TO NEXT SECTOR BEQ 400$ ; IF EQ, ALL FINISHED BR 360$ ; INITIATE NEXT READ 340$: TST U.CW2(R5) ; FILL SILO FUNCTION? BPL 350$ ; IF PL NO BIC #SILO,U.CW2(R5) ; YES - CLEAR SILO BIT JMP 180$ ; GO WRITE SECTOR 350$: CALL NXTSEC ; UPDATE TO NEXT SECTOR BEQ 410$ ; IF EQ, ALL FINISHED 360$: BIC #ERR1,U.CW2(R5) ; CLEAR TIMEOUT ERROR BIT MOV S.PKT(R4),R1 ; RETRIEVE I/O PACKET ADDRESS CMP #IO.SMD,I.FCN(R1) ; SET MEDIA DENSITY FUNCTION? BNE 370$ ; IF NE NO JMP DYSMD ; RETRY IO.SMD 370$: JMP 80$ ; RETRY CURRENT OPERATION NOW 380$: MOV #IE.BLK&377,R0 ; SET BAD BLOCK ERROR BR 440$ ; 390$: MOV #IE.VER&377,R0 ; SET UNRECOVERABLE ERROR BR 420$ ; 400$: MOV I.FCN(R3),R1 ; GET FUNCTION CODE BIC #7,R1 ; REMOVE QUAILFIER BITS CMP #IO.RPB,R1 ; READ PHYSICAL BLOCK? BNE 410$ ; IF NE NO MOV #IS.RDD&377,R0 ; YES, DEFAULT ON READ TO DELETED DATA BITB #DELDAT,U.CW2(R5) ; DELETED DATA READ? BNE 420$ ; IF NE YES 410$: MOV #IS.SUC&377,R0 ; SET SUCCESSFUL COMPLETION CODE 420$: MOV S.PKT(R4),R1 ; GET I/O PACKET ADDRESS MOV I.PRM+4(R1),R1 ; SET BYTES TRANSFERED SUB U.CNT(R5),R1 ; CALCULATE BYTES ACTUALLY TRANSFERED 430$: MOVB S.CON(R4),R3 ; RETRIEVE CONTROLLER INDEX MOVB RTTBL(R3),R2 ; SET FINAL RETRY COUNT MOV S.PKT(R4),R3 ; GET I/O PACKET ADDRESS CMPB #IO.SEC,I.FCN+1(R3) ; IO.SEC OR IO.SMD? BNE 435$ ; IF NE NO BIS #CEW*256.,R2 ; SET INITIAL RETRY COUNT BR 440$ ; 435$: BIS #RETRY*256.,R2 ; SET INITIAL RETRY COUNT 440$: BIC #SILO!SCHAR!ERR1!DELDAT,U.CW2(R5) ; CLEAR BITS CALL @IODON ; SET DONE JMP DYINI ; TRY FOR ANOTHER REQUEST ; ; INTERRUPT PROCESSING POINT FOR DETERMINING THE ; DISKETTE UNIT STATUS. ; DYSEN: MOV S.PKT(R4),R1 ; RETRIEVE I/O PACKET ADDRESS BIT #RSAE,U.CW2(R5) ; READ STATUS AFTER ERROR? BEQ 450$ ; IF EQ NO BIC #RSAE,U.CW2(R5) ; CLEAR FLAG JMP 390$ ; EXIT WITH ERROR 450$: ASRB RTTBL+1(R3) ; INIT IN PROGRESS? BCC 460$ ; IF CC NO BIT #RXACLO,I.PRM+6(R1) ; AC LOW? BNE 460$ ; IF CC NO DECB RTTBL(R3) ; ANY RETRIES LEFT ? BNE 455$ ; IF NE YES JMP 630$ ; IF EQ NO, DON'T RETRY IO.SEC 455$: JMP DYSEC ; RETRY IT 460$: BIT #DRVRDY,I.PRM+6(R1) ; DRIVE READY? BEQ DYRTY ; IF EQ NO TST (R2) ; ANY ERRORS? BPL 470$ ; IF PL NO BIT #DENERR,I.PRM+6(R1) ; IS IT A DENSITY ERROR? BEQ DYRTY ; IF EQ NO 470$: BIC #SCHAR!DEN,U.CW2(R5) ; CLEAR FLAGS MOV #SINGLE,U.CW3(R5) ; ASSUME SINGLE DENSITY BIT #DRVDEN,I.PRM+6(R1) ; IS IT DOUBLE DENSITY? BEQ 480$ ; IF EQ NO ASL U.CW3(R5) ; DOUBLE THE MAXIMUM LBN'S BIS #DEN,U.CW2(R5) ; SET THE DENSITY BIT 480$: MOV #IS.SUC&377,R0 ; SET SUCCESS MOV U.CW2(R5),R1 ; RETURN DEVICE CHARACTERISTICS BR 430$ ; ; ; SENSE CHARACTERISTIC PROCESSING ; DYSEC: BIS #SCHAR,U.CW2(R5) ; INDICATE SENSE CHARACTERISTIC MOV #MRDS,R0 ; SET MAINTENANCE READ STATUS TSTB U.UNIT(R5) ; UNIT 1 ? BEQ 490$ ; IF EQ NO BIS #UNIT,R0 ; YES SELECT UNIT 1 490$: MOVB S.CON(R4),R1 ; RETRIEVE CONTROLLER INDEX MOV R0,CSRSV(R1) ; SAVE FUNCTION CODE MOV R0,(R2) ; INITIATE FUNCTION MOVB S.ITM(R4),S.CTM(R4) ; SET TIMEOUT COUNT BIS #S2.ACT,S.ST2(R4) ; SHOW I/O IS ACTIVE RETURN ; ; ; SET MEDIA DENSITY ; DYSMD: MOV #SETDEN,R0 ; SET FUNCTION CODE BIC #DEN,U.CW2(R5) ; CLEAR FLAG MOV #SINGLE,U.CW3(R5) ; ASSUME SINGLE DENSITY TST I.PRM(R1) ; SINGLE DENSITY? BEQ 500$ ; IF EQ YES CMP #2,I.PRM(R1) ; DOUBLE DENSITY? BNE 500$ ; IF NE NO, TREAT AS SINGLE DENSITY BIS #SDEN,R0 ; DOUBLE DENSITY BIS #DEN,U.CW2(R5) ; UPDATE STATUS ASL U.CW3(R5) ; DOUBLE MAXIMUM LBN'S 500$: TSTB U.UNIT(R5) ; UNIT 1? BEQ 510$ ; IF EQ NO BIS #UNIT,R0 ; YES SELECT UNIT 1 510$: MOVB S.CON(R4),R1 ; RETRIEVE CONTROLLER INDEX MOV R0,CSRSV(R1) ; SAVE FUNCTION CODE MOV R0,(R2) ; INITIATE FUNCTION 520$: BITB #TR!DONE,(R2) ; TRANSFERRED? BMI 530$ ; IF MI YES BEQ 520$ ; IF EQ NO MOV S.PKT(R4),R3 ; GET I/O PACKET ADDRESS MOV RXES(R2),I.PRM+6(R3) ; SAVE STATUS BR DYRTY ; ERROR 530$: MOV #'I,R0 ; ASCII "I" MOVB #30.,S.CTM(R4) ; TIMEOUT COUNT JMP 280$ ; ;+ ; **-DYOUT-FLOPPY DISK TIMEOUT ENTRY POINT ;- DYOUT: CALL LOGTMO ;;; LOG DEVICE TIMEOUT BIS #ERR1,U.CW2(R5) ; SET TIMEOUT ERROR BR DYRTY1 ; ; ; RETRY LAST FUNCTION ; DYRTY: CALL LOGERR ; LOG DEVICE ERROR DYRTY1: MOVB S.CON(R4),R3 ; RESTORE CONTROLLER INDEX MOV S.PKT(R4),R1 ; GET I/O PACKET ADDRESS BIT #RSAE,U.CW2(R5) ; READ STATUS AFTER ERROR? BNE 640$ ; IF NE YES BITB #IQ.X,I.FCN(R1) ; INHIBIT RETRIES ? BEQ 540$ ; IF EQ NO CMP #IO.SEC,I.FCN(R1) ; SENSE CHARACTERISTICS FUNCTION? BEQ 630$ ; IF EQ YES BIS #RSAE,U.CW2(R5) ; SET READ STATUS AFTER ERROR FLAG JMP DYSEC ; GO DO READ STATUS 540$: DECB RTTBL(R3) ; ANY RETRIES LEFT? BNE 550$ ; IF NE YES CMP #IO.SEC,I.FCN(R1) ; DON'T REPEAT IO.SEC FUNCTION BEQ 630$ ; IF EQ EXIT BIS #RSAE,U.CW2(R5) ; SET READ STATUS AFTER ERROR FLAG JMP DYSEC ; GO DO READ STATUS 550$: BIT #ERR1,U.CW2(R5) ; TIMEOUT ERROR? BNE 620$ ; IF NE YES 560$: BIT #RXACLO,I.PRM+6(R1); AC LO ? BEQ 565$ ; NO BR 630$ ; ERROR - POWER OFF 565$: BIT #SCHAR,U.CW2(R5) ; SENSE CHARACTERISTICS FUNCTION ? BNE 620$ ; IF NE YES CMP IO.SMD,I.FCN(R1) ; SET MEDIA DENSTIY FUNCTION? BEQ 620$ ; IF EQ YES BIT #CRCERR,I.PRM+6(R1) ; CRC ERRORS ? BNE 610$ ; IF NE YES 570$: CMP #IO.SMD,I.FCN(R1) ; SET MEDIA DENSITY? BNE 580$ ; IF NE NO JMP DYSMD ; RETRY SET MEDIA DENSITY 580$: MOV I.PRM+10(R1),R0 ; GET LOGICAL SECTOR NUMBER BIT #WCOVFL!DENERR,I.PRM+6(R1) ; WORD COUNT OVERFLOW OR ; DENSITY ERROR ? BEQ 610$ ; IF EQ NO BIT #DRVDEN,I.PRM+6(R1) ; IS IT DOUBLE DENSITY ? BNE 590$ ; IF NE YES BIC #DEN,U.CW2(R5) ; CORRECT IT TO SINGLE DENSITY BIC #SDEN,U.BUF(R5) ; HERE TOO ASL R0 ; MULTIPLY LSN BY 2 MOV #SINGLE,U.CW3(R5) ; CHANGE MAX LBN'S TO SINGLE DENSITY BR 600$ ; 590$: BIS #DEN,U.CW2(R5) ; CHANGE TO DOUBLE DENSITY ASR R0 ; DIVIDE LSN BY 2 MOV #DOUBLE,U.CW3(R5) ; CHANGE MAX LBN'S TO DOUBLE DENSITY 600$: MOV R0,I.PRM+10(R1) ; STORE LOGICAL SECTOR NUMBER 610$: BIC #ERR1,U.CW2(R5) ; CLEAR TIMEOUT ERROR BIT JMP 80$ ; RETRY FUNCTION 620$: MOVB #1,RTTBL+1(R3) ; SET INITIALIZE IN PROGRESS MOV #INIT!INTEBL,CSRSV(R3) ; SAVE FUNCTION CODE MOV #INIT!INTEBL,(R2) ; INITIALIZE RX211 DRIVES MOVB S.ITM(R4),S.CTM(R4) ; SET TIMEOUT COUNTER RETURN ; 630$: BIT #DRVRDY,I.PRM+6(R1) ; DRIVE READY? BEQ 640$ ; IF EQ NO JMP 390$ ; EXIT WITH IE.VER 640$: MOV #IE.DNR&377,R0 ; SET DEVICE NOT READY ERROR JMP 420$ ; EXIT WITH IE.DNR .DSABL LSB ;+ ; *** - TRKSEC - CONVERT LOGICAL OR PHYSICAL BLOCK NUMBER TO ; TRACK-SECTOR PAIR ; ; INPUT: ; R3 - I/O PACKET ADDRESS ; I.PRM+10(R3) - LOGICAL OR PHYSICAL SECTOR ; ; OUTPUT: ; I.PRM+14(R3) - SECTOR (1-26.) ; I.PRM+15(R3) - TRACK (0-76.) ; R3 - UNCHANGED ; C CLEAR - VALID BLOCK ; C SET - BAD BLOCK NUMBER (PHYSICAL OR LOGICAL) ; ;- TRKSEC: MOV I.PRM+10(R3),R1 ; GET LOGICAL OR PHYSICAL BLOCK MOV #8.,R0 ; SET LOOP COUNT MOV #6400,R2 ; SET DIVISOR 10$: CMP R2,R1 ; DOES 26 GO INTO DIVIDEND? BHI 20$ ; IF HI NO (C=0) SUB R2,R1 ; SUBTRACT 26 FROM DIVIDEND SEC ; SET CARRY 20$: ROL R1 ; SHIFT DIVIDEND AND QUOTIENT DEC R0 ; DONE? BGT 10$ ; IF GT NO BISB R1,R0 ; GET TRACK NUMBER CMP R0,#77. ; IS IT A LEGITMATE TRACK NUMBER? BHI 60$ ; IF HI NO BLO 30$ ; IF LO YES BITB #IO.RPB&377,I.FCN(R3) ; PHYSICAL BLOCK FUNCTION? BEQ 60$ ; IF EQ NO, BAD BLOCK ERROR 30$: CLRB R1 ; CLEAR TRACK NUMBER SWAB R1 ; SHIFT DONE SECTOR NUMBER BITB #IO.RPB&377,I.FCN(R3) ; IS IT A PHYSICAL BLOCK NUMBER? BNE 50$ ; IF NE YES CMP #12.,R1 ; NO, C=1 IF 13<=R1<=25 ROL R1 ; DOUBLE FOR INTERLEAVE FACTOR ASL R0 ; ADD TRACK -TRACK SKEW ADD R0,R1 ; SKEW BY 2*TRACK ADD R0,R1 ; SKEW BY 4*TRACK ADD R0,R1 ; SKEW BY 6*TRACK ASR R0 ; RESTORE TRACK NUMBER MOV #26.,R2 ; SET MODULUS 40$: SUB R2,R1 ; MODULO SECTOR INTO RANGE -26. TO -1. BGE 40$ ; IF GE, LOOP UNTIL NEGATIVE ADD R2,R1 ; CONVERT TO RANGE 0-25. INC R0 ; LBN0 STARTS ON TRACK 1 50$: INC R1 ; CONVERT TO RANGE 1-26. MOV R1,I.PRM+14(R3) ; SAVE SECTOR NUMBER BR 70$ ; - BRANCH 60$: SEC ; SIGNAL BAD BLOCK ERROR MOVB R0,I.PRM+15(R3) ; SAVE TRACK NUMBER BR 80$ ; RETURN 70$: MOVB R0,I.PRM+15(R3) ; SAVE TRACK NUMBER CMP #77.*256.,I.PRM+14(R3) ; IS IT A VALID TRACK/SECTOR? 80$: RETURN ; ;+ ; *** - NXTSEC - UPDATE BLOCK NUMBER , BUFFER ADDRESS ; AND BUFFER POINTER ; ; INPUT: ; R3 - I/O PACKET ADDRESS ; R5 - UCB ADDRESS ; I.PRM+10(R3) - CURRENT BLOCK NUMBER ; I.PRM+12(R3) - BYTES TRANSFERED DURING LAST FUNCTION ; U.CNT(R5) - BYTES LEFT TO TRANSFER ; U.BUF(R5) - BUFFER ADDRESS ; ; OUTPUT: ; I.PRM+10(R3) - UPDATED BLOCK NUMBER ; U.BUF(R5) - UPDATED BY 128./256. BYTES ; U.CNT(R5) - UPDATED BY NUMBER OF WORDS TRANSFERED ; Z SET - ALL BYTES TRANSFERED ; Z CLEAR - MORE BYTES TO TRANSFER ; C CLEAR - VALID TRACK/SECTOR ; C SET - BAD BLOCK NUMBER ; ;+ NXTSEC: INC I.PRM+10(R3) ; UPDATE BLOCK NUMBER MOVB S.CON(R4),R0 ; GET CONTROLLER INDEX BIT #DEN,U.CW2(R5) ; SINGLE DENSITY? BEQ 5$ ; IF EQ YES ADD #256.,U.BUF+2(R5) ; UPDATE BUFFER ADDRESS FOR DOUBLE DENSITY BR 10$ ; AND CONTINUE 5$: ADD #128.,U.BUF+2(R5) ; UPDATE BUFFER ADDRESS FOR SINGLE DENSITY 10$: BCC 15$ ; IF CC, NO OVERFLOW ADD #10000,U.BUF(R5) ; CARRY INTO EXTENDED MEMORY BITS 15$: SUB I.PRM+12(R3),U.CNT(R5) ; UPDATE BYTES LEFT TO TRANSFER SUB I.PRM+12(R3),COUNT(R0); UPDATE COUNT FOR IB TST BFLAG(R0) ; BUFFER DATA ? BEQ 100$ ; NO CMPB #IO.WLB/256.,I.FCN+1(R3); WRITE OPERATION ? BEQ 100$ ; YES TST U.CNT(R5) ; ANY MORE DATA TO GET ? BLE 30$ ; NO - MOVE IT BIT #DEN,U.CW2(R5) ; SINGLE DENSITY ? BEQ 26$ ; YES CMP #256.,COUNT(R0) ; MORE ROOM IN IB ? BLE 100$ ; YES BR 30$ ; NO - MOVE THE DATA 26$: CMP #128.,COUNT(R0) ; MORE ROOM IN IB ? BLE 100$ ; YES 30$: MOV BUFLEN(R0),TEMP(R0); NUMBER OF BYTES SUB COUNT(R0),TEMP(R0); TO TRANSFER 32$: CALL BLXIO ; MOVE DATA ADD #<256./100>,DYPTR(R0) ; UPDATE POINTER INTO DYCOM ; (32 WORD BLOCKS) SUB #256.,TEMP(R0) ; UPDATE TEMPORY COUNT FOR MULTIPLE ; FORKS BLE 35$ ; TST @FRKHD ; ANYONE WAITING TO FORK? BEQ 32$ ; IF EQ NO -> DO SOME MORE MOV (SP)+,RETPTR(R0); SAVE RETURN ADDRESS CALL @FORK ; LET SOMEONE ELSE DO SOME WORK MOVB S.CON(R4),R0 ; GET CONTROLLER INDEX MOV S.CSR(R4),R2 ; GET CSR ADDRESS MOV S.PKT(R4),R3 ; GET I/O PACKET ADDRESS MOV RETPTR(R0),-(SP); PUT RETURN ADDRESS ON STACK BR 32$ ; NOW DO SOME MORE WORK 35$: MOV BUFLEN(R0),COUNT(R0); RESET LENGTH OF IB BIC #30000,U.BUF(R5) ; RESET EXTENDED ADDRESSING BITS BIS HIPHYA(R0),U.BUF(R5); TO POINT TO BEG OF IB MOV LOPHYA(R0),U.BUF+2(R5); RESET LO BITS OF IB MOV DYPCB,R1 ; GET PCB OF DATA COMMON MOV P.REL(R1),DYPTR(R0); INITIALIZE POINTER INTO DYCOM TST R0 ; ONE CONTROLLER ? BEQ 100$ ; YES MOV P.SIZE(R1),-(SP); GET SIZE OF REGION ASR (SP) ; CUT IN HALF ADD (SP)+,DYPTR(R0) ; POINT INTO SECOND HALF OF REGION 100$: TST U.CNT(R5) ; IF EQ TO ZERO THEN ALL DONE RETURN ; ; ;+ ; ** -- BLXIO -- MOVE BLOCK OF DATA ROUTINE ; ; THE MOVE BLOCK OF DATA ROUTINE WILL MOVE THE SPECIFIED DATA IN MEMORY ; ;- BLXIO: MOV R0,-(SP) ; SAVE REG MOV R1,-(SP) ; MOV R2,-(SP) ; MOV R3,-(SP) ; MOV R4,-(SP) ; MOV R5,-(SP) ; MOV R3,R5 ; SAVE I/O PACKET ADD MOVB S.CON(R4),R2 ; GET CONTROLLER INDEX MOV PHYADD(R2),R1 ; GET LO BITS OF ADDRESS MOV HIADD(R2),R0 ; GET HI BITS OF ADDRESS ASHC #10.,R0 ; CALCULATE DISP AND BIAS ASHC #-10.,R1 ; CMPB #IO.WLB/256.,I.FCN+1(R5); WRITE FUNCTION ? BEQ 10$ ; YES ADD #APR6DS,R1 ; SET TO MAP THRU APR6 MOV R0,R3 ; DESTINATION APR BIAS MOV R1,R4 ; APR6 DISPLACEMENT CMP #256.,TEMP(R2) ; MORE THAN 256 BYTES TO BLE 5$ ; BE TRANSFERRED ? MOV TEMP(R2),R0 ; NO BR 7$ ; 5$: MOV #256.,R0 ; YES - AT LEAST 256 BYTES TO TRANSFER 7$: ADD R0,PHYADD(R2) ; UPDATE FOR NEXT CALL TO BLXIO ADC HIADD(R2) ; NOT FOR CURRENT CALL MOV DYPTR(R2),R1 ; SOURCE APR5 BIAS MOV #APR5DS,R2 ; SOURCE DISPLACEMENT BR 20$ ; 10$: ADD #APR5DS,R1 ; SET UP TO MAP THRU APR5 CMP #256.,TEMP(R2) ; MORE THAN 256 BYTES TO BLE 17$ ; BE TRANSFERRED ? MOV TEMP(R2),R3 ; NO BR 18$ ; 17$: MOV #256.,R3 ; YES - AT LEAST 256 BYTES TO TRANSFER 18$: ADD R3,PHYADD(R2) ; UPDATE FOR NEXT CALL TO BLXIO ADC HIADD(R2) ; NOT FOR THE CURRENT CALL MOV R3,-(SP) ; SAVE REG MOV DYPTR(R2),R3 ; DESTINATION APR BIAS MOV R1,R2 ; APR DISPLACEMENT MOV R0,R1 ; SOURCE APR BIAS MOV (SP)+,R0 ; RESTORE REG MOV #APR6DS,R4 ; DESTINATION DISPLACEMENT 20$: CALL @BLXI ; MOVE THE DATA MOV (SP)+,R5 ; RESTORE REG MOV (SP)+,R4 ; MOV (SP)+,R3 ; MOV (SP)+,R2 ; MOV (SP)+,R1 ; MOV (SP)+,R0 ; RETURN ;+ ; **-LOGTMO-LOG DEVICE TIMEOUT ; **-LOGERR-LOG DEVICE ERROR ; ; THESE ROUTINES WILL ALLOCATE A CORE BLOCK, FILL IT WITH THE ; REGISTER INFORMATION, CALL THE APPROPRIATE EXECUTIVE ERROR ; LOGGING ROUTINE, DEALLOCATE THE CORE BLOCK, AND RETURN BACK ; TO THE CALLER. ; ; INPUTS: ; R2=CSR ADDRESS ; R4=SCB ADDRESS ; R5=UCB ADDRESS ; ; OUTPUTS: ; SAME AS INPUTS. ; ALL OTHER REGISTERS ARE DESTROYED. ;- .ENABL LSB LOGERR: MOV DVERR,-(SP) ; ADDRESS OF DEVICE ERROR ROUTINE BR 10$ ; LOGTMO: MOV DTOER,-(SP) ;;; ADDRESS OF DEVICE TIMEOUT ROUTINE 10$: MOV #DYNUM*2,R1 ; GET NUMBER OF REGISTERS TO LOG CALL @ALOCB ; ALLOCATE THE REGISTER BLOCK BCC 20$ ; IF CC OK INC @ERRSQ ; INDICATE A MISSED ERROR CMP (SP)+,DTOER ; TIMEOUT ERROR? BNE 30$ ; IF NE NO CLR @S.CSR(R4) ;;; CLEAR INTERRUPT ENABLE MTPS #0 ;;; ALLOW INTERRUPTS BR 30$ ; 20$: MOV R0,R1 ; COPY CORE BLOCK ADDRESS MOV S.CSR(R4),R2 ; RETRIEVE CSR ADDRESS MOV (R2),(R1) ; SAVE CSR CONTENTS MOVB S.CON(R4),R3 ; RETRIEVE CONTROLLER INDEX BIC #^C<17>,CSRSV(R3) ; ISOLATE BITS 0-4 BIS CSRSV(R3),(R1)+ ; INCLUDE FUNCTION CODE MOV RXDB(R2),(R1)+ ; SAVE RXDB .REPT 4 CLR (R1)+ ; ZERO 4 WORDS .ENDR MOV R0,R2 ; GET CORE BLOCK ADDRESS CALL @(SP)+ ; LOG THE ERROR MOV R2,R0 ; GET BACK CORE BLOCK ADDRESS MOV #DYNUM*2,R1 ; GET NUMBER OF BYTES TO DEALLOCATE CALL @DEACB ; DEALLOCATE THE CORE BLOCK 30$: MOV S.CSR(R4),R2 ; RETRIEVE CSR ADDRESS RETURN ; .DSABL LSB .END